#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Gitee仓库批量克隆脚本

用户需求：
此脚本旨在满足用户从Gitee平台批量克隆其个人账号下的所有仓库，以及其创建或参与的所有组织的全部仓库的需求。

脚本功能：
1. 使用Gitee API获取用户个人账号下的所有仓库，并尝试将每个仓库克隆到本地指定目录。
2. 脚本已处理API请求的分页问题，确保能够获取所有仓库信息。
3. 在克隆过程中，如果遇到任何错误，会打印出包含仓库名称和异常信息的错误提示。

使用方法：
1. 将脚本中的 'your_username' 替换为你的Gitee用户名。
2. 生成并替换 'your_access_token' 为有效的Gitee访问令牌（需要有足够的权限查看和克隆仓库）。
3. 确保你已经在本地安装了Python环境，并安装了requests库 (`pip install requests`)。
4. 运行脚本，所有仓库将会被克隆至指定的本地路径下。

注意：
- 请确保正确设置了访问令牌以避免因权限不足导致的问题。
- 脚本可能会受到Gitee API速率限制的影响，请根据实际需求调整请求间隔或申请更高的API访问限额。
"""

import os
import requests
import subprocess
import json

# Gitee 用户名和访问令牌
username = 'your_gitee_username'
access_token = 'your_gitee_token'
repo_json_file = username+'.gitrepos.json'


headers = {
    'Authorization': f'OAuth2 {access_token}',
}

def clone_repo(repo):
    repo_name = repo['name']
    repo_url = repo['html_url']

    local_repo_path = os.path.join(username, repo["full_name"] + '.git')

    if not os.path.exists(local_repo_path) or not os.listdir(local_repo_path):
        os.makedirs(local_repo_path, exist_ok=True)
        try:
            print(f'git clone --mirror {repo_url} {local_repo_path}')
            git_clone_result = subprocess.run(['git', 'clone', '--mirror', repo_url, local_repo_path], capture_output=True, text=True)
            print(f'{repo["full_name"]} cloned. ')
            return
        except Exception as e:
            print(f"Error occurred while cloning repository '{repo_name}':\n{str(e)}")
            shutil.rmtree(local_repo_path)  
    else:
        print(f"Repository '{repo_name}' already exists locally and is not empty. Skipping cloning.")

def fetch_repos(user_api_url, org=False):
    page = 1
    all_repos = []
    while True:
        response_repos = requests.get(f"{user_api_url}?access_token={access_token}&page={page}&per_page=99", headers=headers)
        if response_repos.status_code == 200:
            repos = response_repos.json()
            all_repos.extend(repos)

            # 检查是否有下一页
            if 'total_page' not in response_repos.headers:
                break  # 如果服务器没有返回总页数，则停止循环
            else:
                total_pages = int(response_repos.headers['total_page'])
                if page >= total_pages:
                    break  # 当前页码超过总页数时，停止循环
                else:
                    page += 1  # 增加页码以获取下一页数据
        else:
            print(f"无法获取仓库列表，HTTP状态码：{response_repos.status_code}, Error message: {response_repos.text}")
            break;
    with open(repo_json_file, 'w') as file:
        json.dump(all_repos, file, ensure_ascii=False, indent=4)

if not os.path.exists(repo_json_file):
    fetch_repos(f'https://gitee.com/api/v5/user/repos')
else:
    print(f"The '{repo_json_file}' file already exists. Skipping fetch_repos.")

with open(repo_json_file, 'r') as file:
    try:
        all_repos = json.load(file)
    except FileNotFoundError:
        raise Exception(f"The '{repo_json_file}' file does not exist.")

for repo in all_repos:
    clone_repo(repo)
